package org.databandtech.job.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.ReentrantLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;
import org.apache.commons.collections.CollectionUtils;
import org.databandtech.job.entity.ScheduledBean;
import org.databandtech.job.entity.ScheduledTaskJob;
import org.databandtech.job.mapper.ScheduledMapper;

@Service
public class ScheduledServiceImpl implements ScheduledService {

	private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledServiceImpl.class);

	@Autowired
	private ScheduledMapper taskMapper;
	@Autowired
	private ThreadPoolTaskScheduler threadPoolTaskScheduler;

	private ReentrantLock lock = new ReentrantLock();

	
	@Qualifier(value = "scheduledTaskJobMap")
	@Autowired
	private Map<String, ScheduledTaskJob> scheduledTaskJobMap;

	private Map<String, ScheduledFuture> scheduledFutureMap = new ConcurrentHashMap<>();

	@Override
	public List<ScheduledBean> getAllSchedule() {
		LOGGER.info(">>>>>> 获取任务列表开始 >>>>>> ");
		List<ScheduledBean> taskBeanList = taskMapper.getAll();
		if (CollectionUtils.isEmpty(taskBeanList)) {
			return new ArrayList<>();
		}

		LOGGER.info(">>>>>> 获取任务列表结束 >>>>>> ");
		return taskBeanList;
	}

	@Override
	public Boolean start(String jobcode) {
		LOGGER.info(">>>>>> 启动任务 {} 开始 >>>>>>", jobcode);
		lock.lock();
		LOGGER.info(">>>>>> 添加任务启动锁完毕");
		try {
			if (this.isStart(jobcode)) {
				LOGGER.info(">>>>>> 当前任务已经启动，无需重复启动！");
				return false;
			}
			if (!scheduledTaskJobMap.containsKey(jobcode)) {
				return false;
			}
			ScheduledBean scheduledTask = taskMapper.getByCode(jobcode);
			this.doStartTask(scheduledTask);
		} finally {
			lock.unlock();
			LOGGER.info(">>>>>> 释放任务启动锁完毕");
		}
		LOGGER.info(">>>>>> 启动任务 {} 结束 >>>>>>", jobcode);
		return true;
	}

	private void doStartTask(ScheduledBean scheduledTask) {
        String key = scheduledTask.getJobcode();
        String taskCron = scheduledTask.getCron();
        ScheduledTaskJob scheduledTaskJob = scheduledTaskJobMap.get(key);
        LOGGER.info(">>>>>> 任务 [ {} ] ,cron={}", key, taskCron);
        ScheduledFuture scheduledFuture = threadPoolTaskScheduler.schedule(scheduledTaskJob,
                new Trigger() {
                    @Override
                    public Date nextExecutionTime(TriggerContext triggerContext) {
                        CronTrigger cronTrigger = new CronTrigger(taskCron);
                        return cronTrigger.nextExecutionTime(triggerContext);
                    }
                });
        scheduledFutureMap.put(key, scheduledFuture);
	}

	private boolean isStart(String jobcode) {
		if (scheduledFutureMap.containsKey(jobcode)) {
			if (!scheduledFutureMap.get(jobcode).isCancelled()) {
				return true;
			}
		}
		return false;
	}

	@Override
	public Boolean stop(String jobcode) {
        LOGGER.info(">>>>>> 进入停止任务 {}  >>>>>>", jobcode);
        boolean taskStartFlag = scheduledFutureMap.containsKey(jobcode);
        LOGGER.info(">>>>>> 当前任务实例是否存在 {}", taskStartFlag);
        if (taskStartFlag) {
            ScheduledFuture scheduledFuture = scheduledFutureMap.get(jobcode);
            scheduledFuture.cancel(true);
        }
        LOGGER.info(">>>>>> 结束停止任务 {}  >>>>>>", jobcode);
        return taskStartFlag;
	}

	@Override
	public Boolean restart(String jobcode) {
		this.stop(jobcode);
        return this.start(jobcode);
	}

	@Override
	public void startAllSchedule(List<ScheduledBean> scheduledTaskBeanList) {
		LOGGER.info("程序启动 ==> 初始化所有任务开始 ！size={}", scheduledTaskBeanList.size());
        if (CollectionUtils.isEmpty(scheduledTaskBeanList)) {
            return;
        }
        for (ScheduledBean scheduledTask : scheduledTaskBeanList) {
            String key = scheduledTask.getJobcode();
            if (this.isStart(key)) {
                continue;
            }
            this.doStartTask(scheduledTask);
        }
        LOGGER.info("程序启动 ==> 初始化所有任务结束 ！size={}", scheduledTaskBeanList.size());
	}

}
